package org.linloong.utils;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.async.AsyncRequestNotUsableException;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * video 播放转发
 *
 * @Author: kw
 * @date: 2025-10-18 21:51
 */
@Slf4j
public class VideoFeedUtil {
    public static void videoFeed(String videoFeedUrl, int maxRetries, HttpServletResponse response) {
        response.setContentType("multipart/x-mixed-replace; boundary=frame");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Connection", "close");
        response.setHeader("Access-Control-Allow-Origin", "*");
        log.info("尝试连接视频流地址: {}", videoFeedUrl);
        printIp();

        int retryCount = 0;
        while (retryCount < maxRetries) {
            try (HttpResponse rsp = HttpRequest.get(videoFeedUrl)
                    .setConnectionTimeout(2000)
                    .setReadTimeout(5000)
                    .executeAsync()) {
                log.info("远程服务响应状态: {}", rsp.getStatus());
                log.info("远程服务响应头: {}", rsp.headers());

                try (InputStream inputStream = new BufferedInputStream(rsp.bodyStream());
                     OutputStream outputStream = response.getOutputStream()) {
                    // 尝试读取第一个字节来确认是否有数据
                    inputStream.mark(1);
                    int firstByte = inputStream.read();
                    if (firstByte == -1) {
                        log.warn("响应流为空，第{}次重试", retryCount + 1);
                        retryCount++;
                        Thread.sleep(1000);
                        continue;
                    }
                    inputStream.reset(); // 重置流位置
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    long totalBytes = 0;

                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        // 检查客户端是否已经断开连接
                        if (!response.isCommitted() && Thread.currentThread().isInterrupted()) {
                            throw new AsyncRequestNotUsableException("Client disconnected or thread interrupted");
                        }
                        totalBytes += bytesRead;
                        log.debug("读取到 {} 字节，总计: {} 字节", bytesRead, totalBytes);
                        outputStream.write(buffer, 0, bytesRead);
                        outputStream.flush();
                    }
                    log.info("视频流传输完成，总字节数: {}", totalBytes);
                    break; // 成功传输后退出重试循环
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            } catch (AsyncRequestNotUsableException e) {
                log.warn("客户端中断");
                break;
            } catch (Exception e) {
                retryCount++;
                log.warn("视频流获取失败，第 {} 次重试: {}", retryCount, e.getMessage());
                if (retryCount >= maxRetries) {
                    log.error("视频流转发异常，已达到最大重试次数", e);
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }

    public static void printIp() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return;
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String unknown = "unknown";
        String ip = null;
        try {
            ip = request.getHeader("x-real-ip");
            if (ObjectUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("x-forwarded-for");
            }
            if (ObjectUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ObjectUtils.isEmpty(ip) || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ObjectUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ObjectUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ObjectUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            log.error("IPUtils ERROR ", e);
        }
        log.info("访问IP: {}", ip);
    }
}
